package cn.com.haopy.yue.ai.wx.service;


import cn.com.haopy.yue.ai.core.config.ChatApiProperties;
import cn.com.haopy.yue.ai.core.config.PdfParseApiProperties;
import cn.com.haopy.yue.ai.core.utils.ConstDateFormatUtils;
import cn.com.haopy.yue.ai.core.utils.HttpUtils;
import cn.com.haopy.yue.ai.core.utils.ResponseUtil;
import cn.com.haopy.yue.ai.db.entity.arisk.*;
import cn.com.haopy.yue.ai.db.service.hos.*;
import cn.com.haopy.yue.ai.wx.dto.AIChartMsgResponseDto;
import cn.com.haopy.yue.ai.wx.dto.WxReqPaperDto;
import cn.com.haopy.yue.ai.wx.utils.AIChatParseDataUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.*;


/**
 * 输入异常项或者是指标，得出可能得疾病
 *
 * @author keel
 * @date 2022/4/13
 */
@Service
@Slf4j
public class WxPapersPresIllnessService {


    @Autowired
    private AIRiskPapersService riskPapersService;

    @Autowired
    private AIRiskPapersIndexService riskPapersIndexService;


    @Autowired
    private AIRiskIllnessService riskIllnessService;

    @Autowired
    private ChatAiApiService chatAiApiService;

    @Autowired
    private ChatApiProperties chatProperties;

    @Autowired
    private AIRiskPapersIllnessService riskPapersIllnessService;

    @Autowired
    private AIRiskTopicService riskTopicService;

    @Autowired
    private WxCommonCheckIndexService wxCommonCheckIndexService;

    @Autowired
    AIRiskTopicOptionsService riskTopicOptionsService;

    @Autowired
    AIRiskPapersOptionsService riskPapersOptionsService;

    @Autowired
    WxPapersDrugsService wxPapersDrugsService;

    @Autowired
    AIRiskIllnessTopicService riskIllnessTopicService;

    @Autowired
    CheckReportService checkReportService;

    @Autowired
    PaperIllnessToAISyncService paperIllnessToAISyncService;

    @Autowired
    private PdfParseApiProperties pdfParseApiProperties;


    @Transactional
    public Object createPaperByPreHaopy(Integer userId, WxReqPaperDto wxReqPaperDto) throws Exception {

        //昊邦体检库数据
        JSONArray haopyReporData = checkReportService.checkDetailData(wxReqPaperDto.getCheckNo());


        AIRiskPapers papers = new AIRiskPapers();
        papers.setName(wxReqPaperDto.getName());
        papers.setUserId(userId);
        papers.setMobile(wxReqPaperDto.getMobile());
        papers.setCheckDate(wxReqPaperDto.getCheckDate());
        papers.setCheckNo(wxReqPaperDto.getCheckNo());
        papers.setAge(wxReqPaperDto.getAge());
        papers.setSex(wxReqPaperDto.getSex());

        Map<String, Object> indexParams = new HashMap<>();
        Map<String, Object> info = new HashMap<>();
        info.put("age", wxReqPaperDto.getAge());
        info.put("date", wxReqPaperDto.getCheckDate());
        info.put("name", wxReqPaperDto.getName());
        info.put("series", wxReqPaperDto.getCheckNo());
        info.put("sex", wxReqPaperDto.getSex());
        indexParams.put("info", info);
        //指标 --- 统一格式为pdf 解析为一致的格式
        JSONArray arrJsonIndex = new JSONArray();
        for (int i = 0; i < haopyReporData.size(); i++) {
            JSONObject indexMap = new JSONObject();
            JSONObject haopyIndex = haopyReporData.getJSONObject(i);
            indexMap.put("检查项目", haopyIndex.getString("checkIndexName"));
            indexMap.put("提示", haopyIndex.getString("resultFlag"));
            indexMap.put("正常参考值", haopyIndex.getString("textRef"));
            indexMap.put("测量结果", haopyIndex.getString("resultValue"));
            arrJsonIndex.add(indexMap);
        }

        try {
            //指标标准化-----统一指标
            Map<String, Object> requestParams = new HashMap<>();
            requestParams.put("data", arrJsonIndex);

            JSONObject indexResult = HttpUtils.postJSON(pdfParseApiProperties.getUrl() + "parseIndex", null, requestParams);
            // 转换为json
            if (Objects.nonNull(indexResult)) {
                arrJsonIndex = indexResult.getJSONObject("data").getJSONArray("data");
            }
        } catch (Exception e) {
            log.error(e.toString());
        }

        indexParams.put("data", arrJsonIndex);
        papers.setIndexParams(indexParams);

        Short sex = Short.valueOf("0");
        if (papers.getSex().equals("男")) {
            sex = Short.valueOf("1");
        }
        if (papers.getSex().equals("女")) {
            sex = Short.valueOf("1");
        }


        List<AIRiskPapersIndex> papersIndexList = wxCommonCheckIndexService.getPaperIndexByPdfJson(arrJsonIndex, papers);
        String inputParamsStr = getIndexStr(papersIndexList, papers.getAge());

        Map<String, Object> input_params = new HashMap<>();
        input_params.put("input", inputParamsStr);

        //疾病预测依据指标
        papers.setInputParams(input_params);


        AIChartMsgResponseDto msgResponseDto = chatAiApiService.chatMessage(papers.getId() + "", "", input_params, "预测可能出现的疾病", chatProperties.getPreIllnessKey());


        String answer = msgResponseDto.getAnswer();

        System.out.println(answer);
        JSONObject answerJson = AIChatParseDataUtil.json2Obj(answer);
        JSONArray jsonArray = answerJson.getJSONArray("diseaseName");
        if (jsonArray.size() <= 0) {
            return ResponseUtil.fail("未预测到疾病风险");
        }


        List<AIRiskPapersIllness> saveIllness = getPaperIllness(jsonArray, sex);

        if (saveIllness.size() <= 0) {
            return ResponseUtil.fail("未预测到疾病风险");
        }

        //保存问卷
        riskPapersService.save(papers);

        //疾病
        saveIllness.forEach(item -> {
            item.setPaperId(papers.getId());
        });

        riskPapersIllnessService.saveBatch(saveIllness);

        //指标
        papersIndexList.forEach(item -> {
            item.setPaperId(papers.getId());
        });

        riskPapersIndexService.saveBatch(papersIndexList);

        //问卷
        List<AIRiskPapersOptions> papersOptionsList = getPapersTopic(saveIllness, papers.getId(), sex);

        riskPapersOptionsService.saveBatch(papersOptionsList);


        //保存推荐药品
        wxPapersDrugsService.recommendDrugsByPaperIdNew(papers.getId());


        //异步总结
        paperIllnessToAISyncService.syncPaperSummary(papers.getId());


        return ResponseUtil.ok(papers);
    }


    @Transactional
    public Object createPaperByPreIllnessPdfJson(Integer userId, JSONObject pdfJson) throws Exception {

        try {
            if (Objects.isNull(pdfJson)) {

                ClassPathResource resource = new ClassPathResource("data/check_pdfjson.json");
                byte[] bytes = FileCopyUtils.copyToByteArray(resource.getInputStream());
                String str = new String(bytes, StandardCharsets.UTF_8);

                pdfJson = JSONObject.parseObject(str);
            }

            //基础信息
            JSONObject checkBaseInfo = pdfJson.getJSONObject("info");

            //基础信息
            JSONArray checkIndexArray = pdfJson.getJSONArray("data");


            if (Objects.isNull(checkBaseInfo) || Objects.isNull(checkIndexArray)) {
                return ResponseUtil.fail("未获取到体检数据");
            }

            AIRiskPapers papers = new AIRiskPapers();

            papers.setName(checkBaseInfo.getString("name"));
            papers.setUserId(userId);
            papers.setMobile(checkBaseInfo.getString(""));
            try {
                String date = checkBaseInfo.getString("date");

                if (date.indexOf('年') > -1) {
                    date = date.replace("年", "-").replace("月", "-").replace("日", "");
                }
                papers.setCheckDate(LocalDate.parse(date, ConstDateFormatUtils.shortDateFormat));

            } catch (Exception e) {
                e.printStackTrace();
                log.error(e.toString());
            }

            try {
                Integer age = Integer.parseInt(checkBaseInfo.getString("age").replace("岁", "").replace(" ", ""));
                papers.setAge(age);
            } catch (Exception e) {
                log.error(e.toString());
            }

            papers.setCheckNo(checkBaseInfo.getString("series"));

            papers.setSex(checkBaseInfo.getString("sex"));
            papers.setIndexParams(pdfJson);


            Short sex = Short.valueOf("0");
            if (papers.getSex().equals("男")) {
                sex = Short.valueOf("1");
            }
            if (papers.getSex().equals("女")) {
                sex = Short.valueOf("1");
            }


            List<AIRiskPapersIndex> papersIndexList = wxCommonCheckIndexService.getPaperIndexByPdfJson(checkIndexArray, papers);
            String inputParamsStr = getIndexStr(papersIndexList, papers.getAge());

            System.out.println(inputParamsStr.length());
            Map<String, Object> input_params = new HashMap<>();
            input_params.put("input", inputParamsStr);
            //疾病预测依据指标
            papers.setInputParams(input_params);


            AIChartMsgResponseDto msgResponseDto = chatAiApiService.chatMessage(papers.getId() + "", "", input_params, "预测可能出现的疾病", chatProperties.getPreIllnessKey());


            String answer = msgResponseDto.getAnswer();

            System.out.println(answer);
            JSONObject answerJson = AIChatParseDataUtil.json2Obj(answer);
            JSONArray jsonArray = answerJson.getJSONArray("diseaseName");
            if (jsonArray.size() <= 0) {
                return ResponseUtil.fail("未预测到疾病风险");
            }


            List<AIRiskPapersIllness> saveIllness = getPaperIllness(jsonArray, sex);

            if (saveIllness.size() <= 0) {
                return ResponseUtil.fail("未预测到疾病风险");
            }

            //保存问卷
            riskPapersService.save(papers);

            //疾病
            saveIllness.forEach(item -> {
                item.setPaperId(papers.getId());
            });

            riskPapersIllnessService.saveBatch(saveIllness);

            //指标
            papersIndexList.forEach(item -> {
                item.setPaperId(papers.getId());
            });

            riskPapersIndexService.saveBatch(papersIndexList);

            //问卷
            List<AIRiskPapersOptions> papersOptionsList = getPapersTopic(saveIllness, papers.getId(), sex);

            riskPapersOptionsService.saveBatch(papersOptionsList);


            //保存推荐药品
            wxPapersDrugsService.recommendDrugsByPaperIdNew(papers.getId());

            //异步总结
            paperIllnessToAISyncService.syncPaperSummary(papers.getId());

            return ResponseUtil.ok(papers);


        } catch (Exception e) {
            e.printStackTrace();
        }


        return ResponseUtil.fail("预测评估失败");
    }


    private String getIndexStr(List<AIRiskPapersIndex> papersIndexList, Integer age) {
        String inputParamsStr = "年龄：" + age + " 岁。";
        for (AIRiskPapersIndex paperIndex : papersIndexList) {
            if (paperIndex.getIndexName().equals("年龄")) {
                continue;
            }
            if (StringUtils.hasText(paperIndex.getIndexValue())) {
                inputParamsStr += paperIndex.getIndexName() + "：" + paperIndex.getIndexValue() + "。";
            }
        }

        //inputParamsStr += "预测可能出现的疾病";
        System.out.println("input 字符长度：" + inputParamsStr.length());
        if (inputParamsStr.length() > AIChatParseDataUtil.AiInputLenghth) {
            inputParamsStr = inputParamsStr.substring(0, AIChatParseDataUtil.AiInputLenghth);
        }

        return inputParamsStr;
    }

    private List<AIRiskPapersIllness> getPaperIllness(JSONArray illnessJsonPre, Short sex) {
        List<AIRiskPapersIllness> saveIllness = new ArrayList<>();
        if (illnessJsonPre.size() > 0) {
            List<AIRiskIllness> illnessList = riskIllnessService.listActiveSex(sex);
            for (int i = 0; i < illnessJsonPre.size(); i++) {
                String illnessName = illnessJsonPre.getString(i);
                for (int j = 0; j < illnessList.size(); j++) {
                    AIRiskIllness illnessItem = illnessList.get(j);
                    if (illnessName.equals(illnessItem.getName())) {
                        AIRiskPapersIllness papersIllnessItem = new AIRiskPapersIllness();
                        papersIllnessItem.setIllnessId(illnessItem.getId());
                        papersIllnessItem.setIllnessName(illnessItem.getName());
                        papersIllnessItem.setQuestion(illnessItem.getQuestion());
                        saveIllness.add(papersIllnessItem);
                        break;
                    }
                }

            }
        }
        return saveIllness;
    }

    private List<AIRiskPapersOptions> getPapersTopic(List<AIRiskPapersIllness> papersIllnessList, Integer paperId, Short sex) {
        List<AIRiskPapersOptions> papersOptionsList = new ArrayList<>();
        if (papersIllnessList.size() > 0) {
            List<Integer> ids = new ArrayList<>();
            papersIllnessList.forEach(item -> {
                ids.add(item.getIllnessId());
            });
            //疾病-问题关系
            List<AIRiskIllnessTopic> illnessTopicList = riskIllnessTopicService.getByIllnessIds(ids);
            //问题ID集合
            List<Integer> topicIds = new ArrayList<>();
            illnessTopicList.forEach(item -> {
                topicIds.add(item.getTopicId());
            });
            List<AIRiskTopic> listTopic = riskTopicService.listActiveSexByIds(sex, topicIds);
            for (int i = 0; i < listTopic.size(); i++) {
                AIRiskTopic itemTop = listTopic.get(i);
                List<AIRiskTopicOptions> options = riskTopicOptionsService.listByTopicId(itemTop.getId());
                if (Objects.nonNull(options) && options.size() > 0) {
                    AIRiskPapersOptions papersOptions = new AIRiskPapersOptions();
                    papersOptions.setPaperId(paperId);
                    papersOptions.setTopicId(itemTop.getId());
                    papersOptions.setTopicName(itemTop.getTopic());
                    papersOptions.setIsMultiChoose(itemTop.getIsMultiChoice());
                    papersOptions.setSortIndex(i);
                    List<Map<String, Object>> listArray = new ArrayList<>();
                    options.forEach(optionsItem -> {
                        Map<String, Object> option = new HashMap<>();
                        option.put("name", optionsItem.getOptionName());
                        option.put("value", optionsItem.getOptionName());
                        option.put("checked", false);
                        listArray.add(option);
                    });
                    papersOptions.setOptions(listArray);
                    papersOptionsList.add(papersOptions);
                }

            }
        }
        return papersOptionsList;
    }

}
